package com.yhh.college_information_platform.utils;

import io.minio.*;
import io.minio.errors.*;
import io.minio.http.Method;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.UUID;

/**
 * MinIO工具类
 * 用于文件的上传、下载、删除等操作
 *
 * @author yhh
 * @date 2025-10-25
 */
@Slf4j
@Component
public class MinioUtil {

    @Autowired
    private MinioClient minioClient;

    @Autowired
    private MinioProperties minioProperties;

    /**
     * 上传文件
     *
     * @param file 文件
     * @param bucketName 桶名称
     * @return 文件访问URL
     */
    public String uploadFile(MultipartFile file, String bucketName) throws IOException, ServerException, InsufficientDataException, ErrorResponseException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        // 1. 检查bucket是否存在，不存在则创建
        createBucketIfNotExists(bucketName);

        // 2. 生成唯一文件名
        String originalFilename = file.getOriginalFilename();
        String extension = "";
        if (originalFilename != null && originalFilename.contains(".")) {
            extension = originalFilename.substring(originalFilename.lastIndexOf("."));
        }
        String fileName = UUID.randomUUID().toString().replace("-", "") + extension;

        // 3. 上传文件
        try (InputStream inputStream = file.getInputStream()) {
            minioClient.putObject(
                    PutObjectArgs.builder()
                            .bucket(bucketName)
                            .object(fileName)
                            .stream(inputStream, file.getSize(), -1)
                            .contentType(file.getContentType())
                            .build()
            );
        }

        // 4. 返回文件访问URL
        return getFileUrl(bucketName, fileName);
    }

    /**
     * 上传文件（使用默认bucket）
     *
     * @param file 文件
     * @return 文件访问URL
     */
    public String uploadFile(MultipartFile file) throws IOException, ServerException, InsufficientDataException, ErrorResponseException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        return uploadFile(file, minioProperties.getBucketName());
    }

    /**
     * 检查bucket是否存在，不存在则创建
     *
     * @param bucketName 桶名称
     */
    private void createBucketIfNotExists(String bucketName) throws IOException, ServerException, InsufficientDataException, ErrorResponseException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        boolean exists = minioClient.bucketExists(
                BucketExistsArgs.builder()
                        .bucket(bucketName)
                        .build()
        );
        if (!exists) {
            minioClient.makeBucket(
                    MakeBucketArgs.builder()
                            .bucket(bucketName)
                            .build()
            );
            log.info("创建bucket成功: {}", bucketName);

            // 设置bucket为公共读权限
            String policy = "{\n" +
                    "    \"Version\": \"2012-10-17\",\n" +
                    "    \"Statement\": [\n" +
                    "        {\n" +
                    "            \"Effect\": \"Allow\",\n" +
                    "            \"Principal\": {\"AWS\": [\"*\"]},\n" +
                    "            \"Action\": [\"s3:GetObject\"],\n" +
                    "            \"Resource\": [\"arn:aws:s3:::" + bucketName + "/*\"]\n" +
                    "        }\n" +
                    "    ]\n" +
                    "}";
            minioClient.setBucketPolicy(
                    SetBucketPolicyArgs.builder()
                            .bucket(bucketName)
                            .config(policy)
                            .build()
            );
        }
    }

    /**
     * 获取文件访问URL
     *
     * @param bucketName 桶名称
     * @param fileName 文件名
     * @return 文件访问URL
     */
    public String getFileUrl(String bucketName, String fileName) {
        return minioProperties.getFileHost() + "/" + bucketName + "/" + fileName;
    }

    /**
     * 获取文件预签名URL（用于临时访问私有文件）
     *
     * @param bucketName 桶名称
     * @param fileName 文件名
     * @param expiry 有效期（秒）
     * @return 预签名URL
     */
    public String getPresignedObjectUrl(String bucketName, String fileName, int expiry) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        return minioClient.getPresignedObjectUrl(
                GetPresignedObjectUrlArgs.builder()
                        .method(Method.GET)
                        .bucket(bucketName)
                        .object(fileName)
                        .expiry(expiry)
                        .build()
        );
    }

    /**
     * 删除文件
     *
     * @param bucketName 桶名称
     * @param fileName 文件名
     */
    public void deleteFile(String bucketName, String fileName) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        minioClient.removeObject(
                RemoveObjectArgs.builder()
                        .bucket(bucketName)
                        .object(fileName)
                        .build()
        );
        log.info("删除文件成功: {}/{}", bucketName, fileName);
    }

    /**
     * 删除文件（从URL中提取bucket和文件名）
     *
     * @param fileUrl 文件URL
     */
    public void deleteFileByUrl(String fileUrl) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        // 从URL中提取bucket和文件名
        // URL格式: http://localhost:9000/bucket-name/file-name.ext
        String path = fileUrl.replace(minioProperties.getFileHost() + "/", "");
        String[] parts = path.split("/", 2);
        if (parts.length == 2) {
            deleteFile(parts[0], parts[1]);
        }
    }
}

